<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>不规则曲线-spline-bezier</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
        /* 隐藏body窗口区域滚动条 */
      }
    </style>
    <!--引入three.js三维引擎-->
    <!-- <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script> -->
    <!-- <script src="http://www.yanhuangxueyuan.com/threejs/build/three.js"></script> -->
    <!-- Three.js-master 包示例中的用法 examples/js/controls/OrbitControls.js  版本要匹配-->
    <script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>
    <script src="../../util/OrbitControls.js"></script>
  </head>
  <body>
    <script type="module">
      import { RAFTime, sphereMesh, cylinderMesh } from "../../util/index.js";
      /**
       * 创建场景对象Scene
       */
      var scene = new THREE.Scene();

      /**
       * 辅助坐标系 参数250表示坐标系大小，可以根据场景大小去设置
       */
      var axisHelper = new THREE.AxisHelper(1000);
      scene.add(axisHelper);

      var geometry = new THREE.Geometry(); //声明一个几何体对象Geometry

      //-------------------------------------------------------------- 三维直线LineCurve3
      // //参数：0, 0圆弧坐标原点x，y  100：圆弧半径    0, 2 * Math.PI：圆弧起始角度
      // var arc = new THREE.ArcCurve(0, 0, 100, 0, 2 * Math.PI);
      // // 得到曲线的点数据，曲线的点数据是2维向量
      // var points = arc.getPoints(50); //分段数50，返回51个顶点
      // // 2维向量 转 3维向量
      // var points3D = [];
      // points.forEach((p) => {
      //   points3D.push(new THREE.Vector3(p.x, p.y, 0));
      // });
      // // 这个方式，只支持3维向量，85版本
      // geometry.vertices = points3D;
      // // setFromPoints不存在，85版本
      // // geometry.setFromPoints(points3D);

      //-------------------------------------------------------------- 三维直线LineCurve3
      // var LineCurve = new THREE.LineCurve3(
      //   new THREE.Vector3(50, 0, 0),
      //   new THREE.Vector3(0, 70, 0)
      // );
      // // 得到曲线的点数据，曲线的点是3维向量
      // var pointArr = LineCurve.getPoints(10);
      // // 85版本，setFromPoints不存在
      // // geometry.setFromPoints(pointArr);
      // // 点必须是3维向量，这个版本是
      // geometry.vertices = pointArr;

      //-------------------------------------------------------------- 三维样条曲线  Catmull-Rom算法
      // var curve = new THREE.CatmullRomCurve3([
      //   new THREE.Vector3(-50, 20, 90),
      //   new THREE.Vector3(-10, 40, 40),
      //   new THREE.Vector3(0, 0, 0),
      //   new THREE.Vector3(60, -60, 0),
      //   new THREE.Vector3(70, 0, 80),
      // ]);
      // //getPoints是基类Curve的方法，返回一个vector3对象作为元素组成的数组
      // var points = curve.getPoints(100); //分段数100，返回101个顶点
      // // setFromPoints方法从points中提取数据改变几何体的顶点属性vertices
      // geometry.vertices = points;

      //-------------------------------------------------------------- 三维二次贝赛尔曲线 1个控制点
      // var p1 = new THREE.Vector3(-80, 0, 0);
      // var p2 = new THREE.Vector3(20, 100, 0);
      // var p3 = new THREE.Vector3(80, 0, 0);
      // var curve = new THREE.QuadraticBezierCurve3(p1, p2, p3);
      // var points = curve.getPoints(100);
      // geometry.vertices = points;

      //-------------------------------------------------------------- 三维三次贝赛尔曲线 2个控制点
      var p1 = new THREE.Vector3(-80, 0, 0);
      var p2 = new THREE.Vector3(-40, 100, 10);
      var p3 = new THREE.Vector3(40, 100, 20);
      var p4 = new THREE.Vector3(80, 0, 30);
      var curve = new THREE.CubicBezierCurve3(p1, p2, p3, p4);
      var points = curve.getPoints(100);
      geometry.vertices = points;

      //材质对象
      var material = new THREE.LineBasicMaterial({
        color: 0x000000,
      });
      //线条模型对象
      var line = new THREE.Line(geometry, material);
      scene.add(line); //线条对象添加到场景中

      // 平行光
      var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
      // 平行光辅助对象
      const directionalLightHelper = new THREE.DirectionalLightHelper(
        directionalLight,
        10
      );
      scene.add(directionalLightHelper);
      // 设置光源位置
      directionalLight.position.set(45, 75, 30);
      scene.add(directionalLight);
      // 设置用于计算阴影的光源对象
      directionalLight.castShadow = true;
      // 设置计算阴影的区域，最好刚好紧密包围在对象周围
      // 计算阴影的区域过大：模糊  过小：看不到或显示不完整
      directionalLight.shadow.camera.near = 0.5;
      directionalLight.shadow.camera.far = 300;
      directionalLight.shadow.camera.left = -100;
      directionalLight.shadow.camera.right = 100;
      directionalLight.shadow.camera.top = 200;
      directionalLight.shadow.camera.bottom = -200;
      // 设置mapSize属性可以使阴影更清晰，不那么模糊
      directionalLight.shadow.mapSize.set(1024, 1024);
      console.log(directionalLight.shadow.camera);

      //环境光
      var ambient = new THREE.AmbientLight(0x000000);
      scene.add(ambient);

      /**
       * 相机设置
       */
      var width = window.innerWidth; //窗口宽度
      var height = window.innerHeight; //窗口高度
      var k = width / height; //窗口宽高比
      var s = 100; //三维场景显示范围控制系数，系数越大，显示的范围越大
      //创建相机对象
      var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(60, 60, 60); //设置相机位置
      camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

      /**
       * 创建渲染器对象
       */
      var renderer = new THREE.WebGLRenderer();
      renderer.setSize(width, height); //设置渲染区域尺寸
      renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
      // 设置渲染器，允许光源阴影渲染
      renderer.shadowMap.enabled = true;
      document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

      // // 监听鼠标、键盘事件，实现 旋转/缩放/平移
      // function render() {
      //   renderer.render(scene, camera); //执行渲染操作
      // }

      // 递归函数,每1/60秒左右,调用一次自己
      const render = RAFTime((t) => {
        renderer.render(scene, camera); //执行渲染操作
        // line.rotateY(0.001 * t);
      });

      // 启动渲染
      render();

      // 创建，轨迹控件
      var controls = new THREE.OrbitControls(camera, renderer.domElement);
      // 监听鼠标、键盘事件
      controls.addEventListener("change", render);
    </script>
  </body>
</html>
